package com.zengdada.authority.config.listener.jobs;

import com.alibaba.fastjson.JSONObject;
import com.zengdada.authority.annotation.JobSysLog;
import com.zengdada.authority.annotation.SysLogType;
import com.zengdada.authority.config.quartz.BaseJob;
import com.zengdada.authority.config.quartz.JobAndTriggerManager;
import com.zengdada.authority.exception.RoutineException;
import com.zengdada.authority.model.TimedTask;
import com.zengdada.authority.model.TimedTaskExtend;
import com.zengdada.authority.service.TimedTaskAuthorityService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.util.Date;
import java.util.Map;

/**
 * @Auther: 12614
 * @Contact: 1261438511@qq.com
 * @Date: 2019-03-30 09:00
 * @Description: 普通定时任务父类
 */
public abstract class TimedTaskJob implements BaseJob {

    public static final String TIMED_TASK = "TIMED_TASK";
    @Autowired
    @Qualifier("timedTaskAuthorityServiceImpl")
    TimedTaskAuthorityService timedTaskAuthorityService;
    @Autowired
    JobAndTriggerManager jobAndTriggerManager;

    @Override
    @JobSysLog(value = "定时任务", type = SysLogType.OTHER)
    public void execute(JobExecutionContext context) throws JobExecutionException {
        TimedTask newTimedTask = null;
        try {
            TimedTask timedTask = (TimedTask) context.getJobDetail().getJobDataMap().get(TimedTaskJob.TIMED_TASK);
            TimedTaskExtend timedTaskExtend = JSONObject.parseObject(JSONObject.toJSONString(timedTask), TimedTaskExtend.class);
            TimedTask oldTimedTask = timedTaskAuthorityService.selectById(timedTask.getId());
            Map<String, Object> info = jobAndTriggerManager.getJobInfo(timedTaskExtend.getTriggerKey());
            newTimedTask = new TimedTask();
            newTimedTask.setId(timedTask.getId());
            if (timedTask.getExecutionStrategy() == TimedTaskExtend.STRATEGY_SINGLETON_SKIP) {
                if (oldTimedTask.getTaskRunningState() != 1)
                    run(timedTask, info);
                else
                    timedTaskAuthorityService.updateById(new TimedTask() {{
                        setId(timedTask.getId());
                        setTaskState(String.valueOf(info.get("taskState")));
                        setTaskNextFireTime((Date) info.get("taskNextFireTime"));
                    }});
            } else
                run(timedTask, info);
        } catch (Exception e) {
            RoutineException routineException = new RoutineException(e.getMessage());
            if (newTimedTask != null) newTimedTask.setMessage(routineException.getMessage());
            throw routineException;
        } finally {
            if (newTimedTask != null) {
                newTimedTask.setTaskRunningState(0);
                timedTaskAuthorityService.updateById(newTimedTask);
            }
        }
    }

    private void run(TimedTask timedTask, Map<String, Object> info) throws Exception {
        timedTaskAuthorityService.updateById(new TimedTask() {{
            setId(timedTask.getId());
            setTaskRunningState(1);
            setTaskState(String.valueOf(info.get("taskState")));
            setTaskStartTime((Date) info.get("taskStartTime"));
            setTaskPreviousFireTime((Date) info.get("taskPreviousFireTime"));
            setTaskNextFireTime((Date) info.get("taskNextFireTime"));
        }});
        execute(timedTask);
    }

    public abstract void execute(TimedTask timedTask);

}
